package com.piece.blog.controller;

import com.piece.blog.dto.TrainingExamDTO;
import com.piece.blog.model.TrainingExamInfo;
import com.piece.blog.service.TrainingExamInfoService;
import com.piece.core.framework.annotation.permission.AclPermission;
import com.piece.core.framework.annotation.permission.SubmitPermission;
import com.piece.core.framework.constant.ExceptionConstants;
import com.piece.core.framework.support.bootstrap.DataTable;
import com.piece.core.framework.support.bootstrap.QueryTable;
import com.piece.core.framework.support.convert.Convert;
import com.piece.core.framework.support.convert.PinyinConvert;
import com.piece.core.framework.support.response.AjaxResponse;
import com.piece.core.framework.util.basic.I18nUtil;
import com.piece.core.framework.util.file.FileUtil;
import com.piece.core.framework.util.string.StringUtil;
import com.piece.core.framework.util.time.DateUtil;
import com.piece.core.log.config.UserContextHolder;
import com.piece.core.web.controller.FrameWorkController;
import com.piece.file.client.FileClientFactory;
import com.piece.file.model.TbSysFile;
import com.piece.file.service.TbSysFileService;
import com.piece.module.file.util.pdf.BuilderContext;
import com.piece.module.file.util.pdf.PdfUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 试卷Controller
 *
 * @author onepiece
 * @date 2023-09-12
 */
@RestController
@Api(tags = {"试卷管理"})
@RequestMapping("/api/training/exam")
public class TrainingExamInfoController extends FrameWorkController {

    @Resource
    private TrainingExamInfoService trainingExamInfoService;

    @Resource
    private TbSysFileService tbSysFileService;

    @Autowired
    private FileClientFactory fileClientFactory;

    @PostMapping("/list")
    @AclPermission(code = "training:exam:view")
    @ApiOperation(value = "查询试卷列表")
    @ApiImplicitParam(value = "查询条件", dataTypeClass = QueryTable.class, type = "body")
    public List list() {
        QueryTable queryTable = initTable();
        DataTable dataTable = trainingExamInfoService.findPage(queryTable);
        return dataTable.getData();
    }

    @PostMapping("/table")
    @AclPermission(code = "training:exam:view")
    @ApiOperation(value = "查询试卷分页数据")
    @ApiImplicitParam(value = "查询条件", dataTypeClass = QueryTable.class, type = "body")
    public AjaxResponse table() {
        QueryTable queryTable = initTable();
        DataTable dataTable = trainingExamInfoService.findPage(queryTable);
        return success(dataTable);
    }

    @GetMapping("/load")
    @AclPermission(code = "training:exam:view")
    @ApiOperation(value = "加载试卷表单数据")
    @ApiImplicitParam(name="id", value = "主键")
    public AjaxResponse load() {
        long id = Convert.toLong(getRequest().getParameter("id"), 0L);
        TrainingExamInfo trainingExamInfo = new TrainingExamInfo();
        if (id != 0) {
            trainingExamInfo = trainingExamInfoService.findById(id);
        }
        return success(trainingExamInfo);
    }

    @SubmitPermission
    @PostMapping("/save")
    @AclPermission(code = "training:exam:edit")
    @ApiOperation(value = "保存试卷表单数据")
    @ApiImplicitParam(value = "试卷数据", dataTypeClass = TrainingExamInfo.class, type = "body")
    public AjaxResponse save() {
        TrainingExamInfo trainingExamInfo;
        try {
            Long id = Convert.toLong(getRequest().getParameter("id"));
            if (null != id) {
                trainingExamInfo = trainingExamInfoService.findById(id);
            } else {
                trainingExamInfo = new TrainingExamInfo();
            }
            initDB(trainingExamInfo);
            trainingExamInfoService.insertOrUpdate(trainingExamInfo);
            return success(I18nUtil.message(ExceptionConstants.SAVE_SUCCESS), null);
        } catch (Exception e) {
            return error(I18nUtil.message(ExceptionConstants.SAVE_FAILURE), e.getMessage());
        }
    }

    @SubmitPermission
    @PostMapping("/delete/{id}")
    @AclPermission(code = "training:exam:delete")
    @ApiOperation(value = "删除试卷数据")
    @ApiImplicitParam(name = "id", value = "主键", type = "path")
    public AjaxResponse delete(@PathVariable String id) throws Exception {
        trainingExamInfoService.delete(id);
        return success(I18nUtil.message(ExceptionConstants.DELETE_SUCCESS), null);
    }

    @SubmitPermission
    @PostMapping("/delete")
    @AclPermission(code = "training:exam:delete")
    @ApiOperation(value = "删除试卷数据")
    @ApiImplicitParam(name = "ids", value="主键集合")
    public AjaxResponse deleteBatch() throws Exception {
        String ids = getRequest().getParameter("ids");
        if (StringUtil.isNotEmpty(ids)) {
            trainingExamInfoService.delete(Convert.toLongArray(ids));
        }
        return success(I18nUtil.message(ExceptionConstants.DELETE_SUCCESS), null);
    }

    @SubmitPermission
    @PostMapping("/preview/{examId}")
    @ApiOperation(value = "试卷预览")
    @ApiImplicitParam(name = "id", value="主键", type = "path")
    public AjaxResponse preview(@PathVariable Long examId) throws Exception {
        return success(trainingExamInfoService.preview(examId));
    }

    @SubmitPermission
    @PostMapping("/score")
    @ApiOperation(value = "试卷得分")
    @ApiImplicitParam(value="试卷数据对象", dataTypeClass = TrainingExamDTO.class, type = "body")
    public AjaxResponse score(@RequestBody TrainingExamDTO examInfo) throws Exception {
        return success(trainingExamInfoService.score(examInfo));
    }

    @SubmitPermission
    @PostMapping("/cert/{examId}")
    @ApiOperation(value = "下载考试证书")
    @ApiImplicitParam(name = "id", value = "主键", type = "path")
    public AjaxResponse generateCert(@PathVariable Long examId) {
        InputStream is = null;
        ByteArrayOutputStream os = null;

        try {
            Map<String, String> data = new HashMap<>();
            String name = UserContextHolder.getUserName();
            data.put("userNameCn", name);
            data.put("person", PinyinConvert.toCamelPinYin(name));
            data.put("yearCn", DateUtil.formatDate(new Date(), "yyyy年"));
            data.put("yearEn", DateUtil.formatDate(new Date(), "yyyy"));

            TbSysFile template = tbSysFileService.findFileByTableTemplate("cert_template");
            if (null != template) {
                is = fileClientFactory.get().downloadFile(template);
            } else {
                is = FileUtil.readSystemFile("static/template/cert_template.pdf");
            }

            os = new ByteArrayOutputStream();
            PdfUtil.generateByTemplateStream(is, data, os);
            is.close();
            is = null;
            is = new ByteArrayInputStream(os.toByteArray());
            os.close();
            os = null;
            os = new ByteArrayOutputStream();
            // 添加盖章
            BuilderContext builderContext = new BuilderContext();
            InputStream stamperInputStream = FileUtil.readSystemFile("static/image/stamper.png");
            builderContext.setStamper(FileUtil.toByte(stamperInputStream));
            builderContext.setStamperSizeX(75);
            builderContext.setStamperSizeY(75);
            builderContext.setStamperKey("发证日期");
            builderContext.setStamperPage(1);
            PdfUtil.stamper(is, builderContext, os);

            String filename = "cert_" + examId + ".pdf";
            byte[] bytes = os.toByteArray();
            TbSysFile upload = fileClientFactory.get().writeToStore(bytes, "cert", filename, bytes.length);
            return success(upload.getFileId());
        } catch (Exception e) {
            return error(I18nUtil.message(ExceptionConstants.DOWNLOAD_ERROR), e.getMessage());
        } finally {
            try {
                if (null != os) {
                    os.close();
                    os = null;
                }
                if (null != is) {
                    is.close();
                    is = null;
                }
            } catch (IOException e) {}
        }
    }

    @PostMapping("/question/tableExam/{examId}")
    @AclPermission(code = "training:exam:view")
    @ApiOperation(value = "查询试卷考题分页数据")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "查询条件", dataTypeClass = QueryTable.class, type = "body"),
            @ApiImplicitParam(name = "examId", value = "试卷主键", type = "path")
    })
    public AjaxResponse questionTable(@PathVariable Long examId) {
        QueryTable queryTable = initTable();
        DataTable dataTable = trainingExamInfoService.findQuestionPage(queryTable, examId);
        return success(dataTable);
    }

    @PostMapping("/question/selectExam/{examId}")
    @AclPermission(code = "training:exam:view")
    @ApiOperation(value = "添加试卷考题数据")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "查询条件", dataTypeClass = QueryTable.class, type = "body"),
            @ApiImplicitParam(name = "examId", value = "试卷主键", type = "path")
    })
    public AjaxResponse questionSelect(@PathVariable Long examId) {
        QueryTable queryTable = initTable();
        DataTable dataTable = trainingExamInfoService.findQuestionPageWithoutExam(queryTable, examId);
        return success(dataTable);
    }

    @SubmitPermission
    @PostMapping("/question/addExam/{examId}")
    @AclPermission(code = "training:exam:edit")
    @ApiOperation(value = "添加试卷考题")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ids", value = "主键集合"),
            @ApiImplicitParam(name = "examId", value = "试卷主键", type = "path")
    })
    public AjaxResponse addQuestion(@PathVariable Long examId) throws Exception {
        String ids = getRequest().getParameter("ids");
        if (StringUtil.isNotEmpty(ids)) {
            trainingExamInfoService.addQuestion(examId, Convert.toLongList(ids));
        }
        return success(I18nUtil.message(ExceptionConstants.DELETE_SUCCESS), null);
    }

    @SubmitPermission
    @PostMapping("/question/deleteExam/{examId}")
    @AclPermission(code = "training:exam:delete")
    @ApiOperation(value = "删除试卷考题")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ids", value = "主键集合"),
            @ApiImplicitParam(name = "examId", value = "试卷主键", type = "path")
    })
    public AjaxResponse deleteQuestion(@PathVariable Long examId) throws Exception {
        String ids = getRequest().getParameter("ids");
        if (StringUtil.isNotEmpty(ids)) {
            trainingExamInfoService.deleteQuestion(examId, ids);
        }
        return success(I18nUtil.message(ExceptionConstants.DELETE_SUCCESS), null);
    }
}
